/*
 * Copyright 2013 Agustina Martinez-Garcia

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package uk.ljmu.qudexapps.manager.domain;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.binding.message.MessageBuilder;
import org.springframework.binding.message.MessageContext;
import org.springframework.binding.validation.ValidationContext;
import org.springframework.web.multipart.MultipartFile;

import uk.ljmu.metadata.utilities.MetadataUtilities;
import uk.ljmu.qudexapps.manager.listeners.CustomServletContextAware;
import uk.ljmu.qudexapps.manager.utilities.Constants;
import uk.ljmu.qudexapps.manager.utilities.GeneralUtilities;
import uk.ljmu.qudexapps.manager.utilities.WebUtils;

public class FilesModel implements Serializable {

    transient private static Logger log = Logger.getLogger(FilesModel.class);
    /**
     * Auto-generated by Eclipse IDE
     */
    private static final long serialVersionUID = 4638366732733985722L;

    /**
     * 0 - Collection-level spreadsheet 1 - File-level spreadsheet
     */
    private String option;

    /**
     * The uploaded spreadsheet
     */
    transient private MultipartFile spreadsheet;
    /**
     * Name of temporary directory holding the user uploaded files
     */
    private String tempDirName = "";
    
    private String emailAddress = "";
    /**
     * Path to the temporary directory holding the user uploaded files
     */
    private String tempDirPath = "";
    /**
     * Parent collection ID - used when uploading file-level spreadsheets
     * Collection level spreadsheets are root collections or could be
     * sub-collections, if the latter, then this fields would be relevant as
     * well
     */
    private String collectionsIds = "";
    /**
     * Auto-filled spreadsheet copy of the original one uploaded
     */
    transient private InputStream modifiedSpreadsheet;
    /**
     * Uploaded zip file containing raw data uploaded
     */
    transient private List<MultipartFile> zipFiles;
    
    transient private MultipartFile zfile;
    
    private Relation relationObject;

    /**
     * @param tempDirPath
     *            the tempDirPath to set
     */
    public void setTempDirPath(String tempDirPath) {
	this.tempDirPath = tempDirPath;
    }

    /**
     * @return the tempDirPath
     */
    public String getTempDirPath() {
	return tempDirPath;
    }

    /**
     * @param emailAddress the emailAddress to set
     */
    public void setEmailAddress(String emailAddress) {
	this.emailAddress = emailAddress;
    }

    /**
     * @return the emailAddress
     */
    public String getEmailAddress() {
	return emailAddress;
    }

    /**
     * @param option
     *            the option to set
     */
    public void setOption(String option) {
	this.option = option;
    }

    /**
     * @return the option
     */
    public String getOption() {
	return option;
    }

    /**
     * @param zfile the zfile to set
     */
    public void setZfile(MultipartFile zfile) {
	this.zfile = zfile;
    }

    /**
     * @return the zfile
     */
    public MultipartFile getZfile() {
	return zfile;
    }

    public void setTempDirName(String tempDirName) {
	this.tempDirName = tempDirName;
    }

    public String getTempDirName() {
	return tempDirName;
    }

    public void setSpreadsheet(MultipartFile fedoraFile) {
	this.spreadsheet = fedoraFile;
    }

    public MultipartFile getSpreadsheet() {
	return spreadsheet;
    }

    public void setCollectionsIds(String collectionsIds) {
	this.collectionsIds = collectionsIds;
    }

    public String getCollectionsIds() {
	return collectionsIds;
    }

    public void setZipFiles(List<MultipartFile> zipFileList) {
	this.zipFiles = zipFileList;
    }

    public List<MultipartFile> getZipFiles() {
	return zipFiles;
    }

    public void setModifiedSpreadsheet(InputStream modifiedSpreadsheet) {
	this.modifiedSpreadsheet = modifiedSpreadsheet;
    }

    public InputStream getModifiedSpreadsheet() {
	return modifiedSpreadsheet;
    }
    
    public Relation getRelationObject() {
		return relationObject;
	}

	public void setRelationObject(Relation relationObject) {
		this.relationObject = relationObject;
	}

	public void addZipFile(MultipartFile file) {
    	if (file.getSize() <= Constants.FILE_MAX_MEM_SIZE)
    		this.zipFiles.add(file);
    	else {
    		try {
				file.transferTo(new File(this.tempDirPath + System.getProperty("file.separator") + file.getOriginalFilename()));
				this.zipFiles.add(file);
			} catch (IllegalStateException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }
    
    public void deleteZipFile(int index) {
	try {
	    this.zipFiles.remove(index);
	} catch (IndexOutOfBoundsException ex) {
	    
	}
    }
    public void cleanZipFiles() {
	for (MultipartFile file : this.zipFiles) {
	    try {
	    	
	    	if (file.getSize() <= Constants.FILE_MAX_MEM_SIZE && file.getInputStream() != null)
	    		file.getInputStream().close();
	    } catch (IOException e) {
	    }
	}
	this.zipFiles.clear();
    }
    
    public void validateCollectionUpload(ValidationContext context) {
	MessageContext messages = context.getMessageContext();
	if (this.collectionsIds.contains("NULLVALUE")) {
	    messages.addMessage(new MessageBuilder().error().source(
		"filesModel.collectionsIds").code("invalidCollection")
		.build());
	    return;
	}
	// ZIP present
	if (this.getSpreadsheet().getOriginalFilename() == "") {
	    messages.addMessage(new MessageBuilder().error().source(
		    "filesModel.spreadsheet").code("noFilesSelected").build());
	    return;
	}
	if (this.getSpreadsheet().getOriginalFilename() != "") {

	    if (!this.getSpreadsheet().getContentType().equals(
		    "application/vnd.ms-excel")
		    && !this.getSpreadsheet().getContentType().equals(
			    "text/csv")
		    && !this.getSpreadsheet().getContentType().equals(
			    "application/ms-excel")
		    && !this.getSpreadsheet().getContentType().equals(
			    "application/x-msexcel")) {
		messages.addMessage(new MessageBuilder().error().source(
			"filesModel.spreadsheet").code("invalidFedoraFile")
			.build());
	    }
	}
    }
    public void validateSelectZipFile(ValidationContext context) {
	MessageContext messages = context.getMessageContext();
	if (!this.zfile.getOriginalFilename().equals("") && this.zfile.getSize() > 0) {
	    if (!this.zfile.getContentType().equals(
		MetadataUtilities.MIMETYPES_MAP.get("zip"))
		&& !this.zfile.getContentType().equals(
			MetadataUtilities.MIMETYPES_MAP.get("zip2"))
		&& !this.zfile.getContentType().equals(
			MetadataUtilities.MIMETYPES_MAP.get("zip3"))
		&& !this.zfile.getContentType().equals(
			MetadataUtilities.MIMETYPES_MAP.get("zip4"))
		&& !this.zfile.getContentType().equals(
			MetadataUtilities.MIMETYPES_MAP.get("zip5"))
		&& !this.zfile.getContentType().equals(
			MetadataUtilities.MIMETYPES_MAP.get("gtar"))
		&& !this.zfile.getContentType().equals(
			MetadataUtilities.MIMETYPES_MAP.get("gzip"))
		&& !this.zfile.getContentType().equals(
			MetadataUtilities.MIMETYPES_MAP.get("tar"))) {
			messages.addMessage(new MessageBuilder().error().source(
			"filesModel.zfile").code("invalidZipFile")
			.build());
		}
	} else {
	    messages.addMessage(new MessageBuilder().error().source(
		"filesModel.zfile").code("noFilesSelectedZip")
		.build());
	}
    }
    
    public void validateShowResultsCollection(ValidationContext context) {
	MessageContext messages = context.getMessageContext();
	if (!WebUtils.isValidEmailAddress(this.emailAddress)) {
	    messages.addMessage(new MessageBuilder().error().source(
	    "filesModel.emailAddress").code("invalidEmailAddress").build());
	}
	    
    }
    public void validateFileUpload(ValidationContext context) {
	MessageContext messages = context.getMessageContext();
	if (this.collectionsIds.contains("NULLVALUE")) {
	    messages.addMessage(new MessageBuilder().error().source(
		"filesModel.collectionsIds").code("invalidCollection")
		.build());
	    return;
	}
	if (this.getSpreadsheet().getOriginalFilename() == "") {
	    messages.addMessage(new MessageBuilder().error().source(
		    "filesModel.spreadsheet").code("noFilesSelected").build());
	} else {
	    if (!this.getSpreadsheet().getContentType().equals(
		    "application/vnd.ms-excel")
		    && !this.getSpreadsheet().getContentType().equals(
			    "text/csv")
		    && !this.getSpreadsheet().getContentType().equals(
			    "application/ms-excel")
		    && !this.getSpreadsheet().getContentType().equals(
			    "application/x-msexcel")) {
		messages.addMessage(new MessageBuilder().error().source(
		"filesModel.spreadsheet").code("invalidFedoraFile")
		.build());
	    }
	    String[] collectionsArray = this.getCollectionsIds().split(";");
	    // Check that only one collection ID is provided
	    if (collectionsArray.length > 1) {
		// Error
		messages.addMessage(new MessageBuilder().error().source(
			"filesModel.collectionsIds").code("multipleIds")
			.build());
	    }
	}
    }

    public void init() {
	File sessionTempDir = (File) CustomServletContextAware
		.getMyServletContext().getAttribute(
			"javax.servlet.context.tempdir");
	File tempDir;
	try {
	    tempDir = File.createTempFile("swf", "qudex", sessionTempDir);
	    if (!(tempDir.delete())) {
		throw new IOException("Could not delete temp file: "
			+ tempDir.getAbsolutePath());
	    }

	    if (!(tempDir.mkdir())) {
		throw new IOException("Could not create temp directory: "
			+ tempDir.getAbsolutePath());
	    }

	    this.setTempDirName(tempDir.getName());
	    this.setTempDirPath(tempDir.getAbsolutePath());
	    this.zipFiles = new ArrayList<MultipartFile>();
	    this.relationObject = new Relation();
	} catch (IOException e) {
	    log.error("Error in init: ", e);
	}
    }
    public void deleteTemporaryFiles() {
	File tempDir = new File(this.getTempDirPath());
	if (tempDir.exists()) {
	    boolean results = GeneralUtilities.deleteDirectory(tempDir);
	    if (!results) {
		log.error("Temporary directory not deleted: "
			+ tempDir.getAbsolutePath());
	    } else {
		try {
		    tempDir = new File(this.getTempDirPath());
		    if (!(tempDir.mkdir())) {
			throw new IOException("Could not create temp directory: "
				+ tempDir.getAbsolutePath());
		    }
		} catch (IOException e) {
		    log.error("Error in deleteTemporaryFiles: ", e);
		}
	    }
	}
    }
    public void destroy() {
	File tempDir = new File(this.getTempDirPath());
	if (tempDir.exists()) {
	    boolean results = GeneralUtilities.deleteDirectory(tempDir);
	    if (!results) {
		log.error("Temporary directory not deleted: "
			+ tempDir.getAbsolutePath());
	    }
	}

    }
}